package com.ycb.seata;

import java.sql.Connection;
import java.time.LocalDateTime;
import java.util.Optional;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import java.util.function.Function;

import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;

import io.seata.core.model.GlobalStatus;
import io.seata.rm.RMClient;
import io.seata.tm.TMClient;
import io.seata.tm.api.GlobalTransaction;
import io.seata.tm.api.GlobalTransactionContext;

@Slf4j
public class App {

	static {
		String applicationId = "n2";
		String transactionServiceGroup = "my_tx_group";
		TMClient.init(applicationId, transactionServiceGroup);
		RMClient.init(applicationId, transactionServiceGroup);
	}
	static int amt = 100;
	static CountDownLatch countDownLatch = new CountDownLatch(2);
	volatile static String xid = null;
	public static void main(String[] args) throws Exception {

		GlobalTransaction tx = GlobalTransactionContext.getCurrentOrCreate();
		tx.begin();
		xid = tx.getXid();
		try{
			exec((x)-> DBUtils.getSeataSqlSession().getMapper(OrderMapper.class).addAmt(1002, amt),false );
			exec((x)-> DBUtils.getSeataSqlSession().getMapper(OrderMapper.class).subAmt(1001, amt),false );
			tx.commit();
		}catch (Exception e){
			tx.rollback();
		}
	}


	public static void exec(Function<Integer,Integer> func,boolean ex) throws Exception {
		new Thread() {
			public void run() {
				try {
					log.error(" xid : {}",xid);
					GlobalTransaction tx = GlobalTransactionContext.createNew();
					try {
						tx.begin();
						xid = tx.getXid();
						log.info("xid :{} tx.getLocalStatus() : {}",xid,tx.getLocalStatus());
						func.apply(1);
						if(ex) {
							int x = 10/0;
						}
						tx.commit();
					} catch (Exception e) {
						tx.rollback();
						System.err.println("异常 "+e.getMessage());
					}finally {
						countDownLatch.countDown();
						log.info("xid :{} tx.getLocalStatus() : {} close bye",xid,tx.getLocalStatus());
					}
				} catch (Exception e) {
					e.printStackTrace();
				}
			};
		}.start();


	}

	
	public void failConfig()  throws Exception {
		SqlSession sqlSession1 =null;
		SqlSession sqlSession2 = null;
		SqlSessionFactory sqlSessionFactory1 = DBUtils.getSeataSqlSessionFactory();
		SqlSessionFactory sqlSessionFactory2 = DBUtils.getSeataSqlSessionFactory();
		GlobalTransaction  tx = GlobalTransactionContext.getCurrentOrCreate();
		GlobalStatus status = tx.getStatus();
		System.err.println("GlobalStatus 1  =  "+ status);
		 sqlSession1 = sqlSessionFactory1.openSession();
		 sqlSession2 = sqlSessionFactory2.openSession();
		tx.begin();
		System.err.println("GlobalStatus 2  =  "+ status);
		try {
			OrderMapper or1 = sqlSession1.getMapper(OrderMapper.class);
			OrderMapper or2 = sqlSession2.getMapper(OrderMapper.class);
			int addAmt = or1.addAmt(1001, amt);
			int subAmt = or2.subAmt(1002, amt);		
			tx.commit();
			System.err.println("addAmt = "+addAmt + "  subAmt  = "+subAmt);
		} catch (Exception e) {
			tx.rollback();
			System.err.println("异常 "+e.getMessage());
		}finally {
			sqlSession1.close();
			sqlSession2.close();
			System.err.println(" close bye");
		}
	}
	
	public void oldDefaultseata() throws Exception {
		SqlSession sqlSession1 =null;
		SqlSession sqlSession2 = null;
		GlobalTransaction  tx = GlobalTransactionContext.getCurrentOrCreate();
		tx.begin();
		try {
			 sqlSession1 = DBUtils.getSqlSession();
			 sqlSession2 = DBUtils.getSqlSession();
			OrderMapper or1 = sqlSession1.getMapper(OrderMapper.class);
			OrderMapper or2 = sqlSession2.getMapper(OrderMapper.class);
			int addAmt = or1.addAmt(1001, amt);
			int subAmt = or2.subAmt(1002, amt);		
//			int x = 10/0;
			tx.commit();
			System.err.println("addAmt = "+addAmt + "  subAmt  = "+subAmt);
			
//			sqlSession1.commit();
//			sqlSession2.commit();
		} catch (Exception e) {
			tx.rollback();
//			sqlSession1.rollback();
//			sqlSession2.rollback();
			
			System.err.println("异常 "+e.getMessage());
		}finally {
			sqlSession1.close();
			sqlSession2.close();
			System.err.println(" close bye");
		}
	}
	
	
	public static void defaultTranction() {
		System.out.println("begin amt ="+amt);
		SqlSession session = DBUtils.getSqlSession();
		OrderMapper orMapper = session.getMapper(OrderMapper.class);
		int addAmt = orMapper.addAmt(1001, amt);
		int subAmt = orMapper.subAmt(1002, amt);
		session.commit();
		session.close();
		System.err.println("ok addAmt = "+addAmt+"  subAmt = "+subAmt);
	}
	
}
